Undo redo with Svelte stores
Posted on 2023-03-30 by
henrikvilhelmberglundHere we want to implement undo/redo using Svelte stores.
This is the first approach: storing a history of actions applied to the store
0
<script>
import { writable } from "svelte/store";
import approach1 from "./approach1";
const store = writable(0);
let value = 1;
// action creator
function sum(value) {
return {
apply(_value) {
return _value + value;
},
reverse(_value) {
return _value - value;
},
};
}
const undoRedoStore = approach1(store);
</script>
<div class="p-4">
<button
on:click={() => {
undoRedoStore.undo();
}}>Undo</button>
<button
on:click={() => {
undoRedoStore.redo();
}}>Redo</button>
<input bind:value type="number" />
<button
on:click={() => {
// $undoRedoStore += value;
undoRedoStore.doAction(sum(value));
value = 0;
}}>Add</button>
<p>
{$undoRedoStore}
</p>
</div>
<style>
</style>
Both of these approaches works fine if we want to store a primary type like numbers or strings .
But, what if we want to store an object ?
Here we are going to use an object! ... except it doesn't work because we're referencing the same object in our store.
{"value":0} 0
[{"value":0}]
<script>
import { writable } from "svelte/store";
import approach3 from "./approach3";
const store = writable({ value: 0 });
let value = 1;
const undoRedoStore = approach3(store);
const history = undoRedoStore.history;
</script>
<div class="p-4">
<button
on:click={() => {
undoRedoStore.undo();
}}>Undo</button>
<button
on:click={() => {
undoRedoStore.redo();
}}>Redo</button>
<input bind:value type="number" />
<button
on:click={() => {
$undoRedoStore.value += value;
value = 0;
}}>Add</button>
<p>
{JSON.stringify($undoRedoStore)}
{$undoRedoStore.value}
</p>
<p>{JSON.stringify($history)}</p>
</div>
<style>
</style>